//
//  Utility.h
//  germ
//
//  Created by Rodger Voelker on 9/15/04.
//  Purpose: Provide some input utilites, such as : read the command line switches and map to variable, query driven user input, and conversion of strings to other data types
//

#ifndef __germ__Utility__
#define __germ__Utility__

#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <map>
#include <cctype>
#include <algorithm>

using namespace std;

// Assumes switch/value pairs separated by white space
// 'initialize' fills the map with switch value pairs
// The 'mapSwitch' function assigns the value mapped to a switch to the variable passed to the function
// it returns true on success and false if the switch can not be found

class Utility{
public:
  //		Utility();
  //Utility(int argc, char* argv[]); //can't use this form because we always want to check the return state for success
  //		~Utility();
  //accessing argv
  bool getArguments(int argc, char* argv[]); //returns false if odd number of arguments passed
  int argvSize(); //return number of elements found minus arg 0
  vector<string> copyArgv(); //read line into new vector<string>
  map<string,string> copyMap(); //read map into new map
  void print(); //print contents of map to standard output
  bool mapSwitch(const char* theSwitch, int& variable); //assign value mapped to theSwitch to variable
  bool mapSwitch(const char* theSwitch, double& variable); //assign value mapped to theSwitch to variable
  bool mapSwitch(const char* theSwitch, const char* &variable); //assign value mapped to theSwitch to variable
  bool mapSwitch(const char* theSwitch, string& variable); //assign value mapped to theSwitch to variable
  bool mapSwitch(const char* theSwitch, unsigned& variable); //assign value mapped to theSwitch to variable
  bool mapSwitch(const char* theSwitch, long& variable); //assign value mapped to theSwitch to variable
  bool mapSwitch(const char* theSwitch, float& variable); //assign value mapped to theSwitch to variable
  bool mapSwitch(const char* theSwitch, bool& variable);
  //getting input from user
  //get as Int
  int getInt( string query_message );
  int getIntWithDefault( string query_message, int default_value );
  int getIntWithBounds( string query_message, int lowrange, int highrange);
  int getIntWithDefaultWithBounds( string query_message, int default_value, int lowrange, int highrange);
  //get as Unsinged
  unsigned getUnsigned( string query_message );
  unsigned getUnsignedWithDefault( string query_message, unsigned default_value );
  unsigned getUnsignedWithBounds( string query_message, unsigned lowrange, unsigned highrange);
  unsigned getUnsignedWithDefaultWithBounds( string query_message, unsigned default_value, unsigned lowrange, unsigned highrange);
  //get as long
  long getLong( string query_message );
  long getLongWithDefault( string query_message, long default_value );
  long getLongWithBounds( string query_message, long lowrange, long highrange);
  long getLongWithDefaultWithBounds( string query_message, long default_value, long lowrange, long highrange);
  //get as double
  double getDouble( string query_message );
  double getDoubleWithDefault( string query_message, double default_value );
  double getDoubleWithBounds( string query_message, double lowrange, double highrange);
  double getDoubleWithDefaultWithBounds( string query_message, double default_value, double lowrange, double highrange);
  //get as float
  float getFloat( string query_message );
  float getFloatWithDefault( string query_message, float default_value );
  float getFloatWithBounds( string query_message, float lowrange, float highrange);
  float getFloatWithDefaultWithBounds( string query_message, float default_value, float lowrange, float highrange);
  //get as bool
  bool getBool( string query_message );
  bool getBoolWithDefault( string query_message, bool default_value );
  //get as string
  string getString( string query_message );
  string getStringWithDefault( string query_message, string default_value );
  //type conversions, these also provide the conversions for the other member functions
  int stringToInt( string& input_string );
  unsigned stringToUnsigned( string& input_string );
  long stringToLong( string& input_string );
  double stringToDouble( string& input_string );
  float stringToFloat( string& input_string );
  unsigned long stringToUnsignedLong( string& input_string );
  void toUpper( string& instring );
  //substr (see code for description)
  string substr( const string& instring, int offset, int sublen, int anchor, bool use_strict );
  //utility
  string getFileNamePrefix( string& input_string); //used to get that part of the name before the period
  string getFileNameSuffix( string& input_string); //used to get that part of the name after the period
  bool verifyFileExists(string& file); //The name says it all
  unsigned splitSpace( string& input, vector<string>& output ); //split input string on spaces, return number of fields found
  unsigned splitSpace( string& input, vector<int>& output ); //split input string on spaces, return number of fields found
  unsigned splitTab( string& input, vector<string>& output ); //split input string on tabs, return number of fields found
  unsigned splitComma( string& input, vector<string>& output ); //split input string on commas, return number of fields found
  unsigned splitLower(string& instring, vector<string>& outvec);
  unsigned split( string& input, vector<string>& output, char delimiter );
  //nucleotide conversion
  bool seqToBase10( const string& seq, int& nb10 ); //used to convert a string of nucleotides to a base10 equiv
  bool base10ToSeq( int n, string& seq, int patlen ); //used to convert a base 10 number to a nucleotide equivalent
private:
  vector<string> _argv; //the arguments read from the command line minus arg 0
  map<string,string> _commands; //map containing switch/value pairs keyed by switch
  vector<string> _splitPeriod( string& instring );
  struct NotPeriod {
    bool operator() (char value) const{
      return (value != '.' ? true : false);
    }
  };
  struct NotComma {
    bool operator() (char value) const
    {
      return (value != ',' ? true : false);
    }
  };
  struct NotSpace {
    bool operator() (char value) const
    {
      return (value != ' ' ? true : false);
    }
  };
  struct NotTab {
    bool operator() (char value) const
    {
      return (value != '\t' ? true : false);
    }
  };
  struct NotDelimiter {
    bool operator() (char value, char delimiter) const
    {
      return (value != delimiter ? true : false);
    }
  };
  struct NotLower {
    bool operator() (char c) const
    {
      return ((std::isupper(c)) ? true : false);
    }
  };
  struct NotUpper {
    bool operator() (char c) const
    {
      return ((std::islower(c)) ? true : false);
    }
  };
  
};

#endif /* defined(__germ__Utility__) */
